package com.nothing.controller;

import java.awt.image.BufferedImage;
import java.net.URL;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicReference;

import javax.annotation.PostConstruct;

import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.FrameGrabber;
import org.bytedeco.javacv.Java2DFrameConverter;
import org.bytedeco.javacv.OpenCVFrameGrabber;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Controller;

import com.arcsoft.face.FaceInfo;
import com.github.sarxos.webcam.Webcam;
import com.github.sarxos.webcam.WebcamCompositeDriver;
import com.github.sarxos.webcam.ds.buildin.WebcamDefaultDriver;
import com.github.sarxos.webcam.ds.ipcam.IpCamAuth;
import com.github.sarxos.webcam.ds.ipcam.IpCamDevice;
import com.github.sarxos.webcam.ds.ipcam.IpCamDeviceRegistry;
import com.github.sarxos.webcam.ds.ipcam.IpCamDriver;
import com.github.sarxos.webcam.ds.ipcam.IpCamMode;
import com.nothing.config.StageManager;
import com.nothing.controller.OpenCVPreviewController.TakeFace;
import com.nothing.controller.WebCamPreviewController.MyCompositeDriver;
import com.nothing.domain.UserFaceGroup;
import com.nothing.dto.WebCamInfo;
import com.nothing.hessian.config.HessionServiceConfig;
import com.nothing.hessian.service.CheckFaceService;
import com.nothing.service.FaceEngineService;
import com.nothing.service.UserFaceImgService;
import com.nothing.service.UserFaceInfoService;
import com.nothing.util.ExcutorUtil;
import com.nothing.view.FxmlView;

import cn.hutool.core.collection.CollectionUtil;
import javafx.application.Platform;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.concurrent.Task;
import javafx.embed.swing.SwingFXUtils;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.image.WritableImage;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.Pane;

/**
 * 调用网络摄像头
 * 
 * @author shíQíang㊚
 */
@Controller 
public class DrawController implements Initializable{
	
	/**
	 * Customized webcam driver.
	 */
	public static class MyCompositeDriver extends WebcamCompositeDriver {

		public MyCompositeDriver() {
			add(new WebcamDefaultDriver());
			add(new IpCamDriver());
		}
	}
	//----选择驱动
	static{
		Webcam.setDriver(new MyCompositeDriver()); 
	}
	
	//----初始化摄像头
	@PostConstruct
    public void init(){
		try {
			for(String cam : HessionServiceConfig.camHost){
				String[] register = cam.split(",");
				IpCamDeviceRegistry.register(new IpCamDevice(register[0]+"1",register[1], IpCamMode.PUSH,
						new IpCamAuth(register[2],register[3]))); 	
			} 
		} catch (Exception e){
			e.printStackTrace();
		}
    }
	
	@FXML
	Button btnStartCamera;
	@FXML
	Button btnStopCamera;
	@FXML
	Button btnDisposeCamera;
	@FXML
	Button btnBackToUser;
	@FXML
	Button btnCheck;
	@FXML
	Button takePicture;
	@FXML
	ComboBox<WebCamInfo> cbCameraOptions;
	@FXML
	BorderPane bpWebCamPaneHolder;
	@FXML
	FlowPane fpBottomPane;
	@FXML
	ImageView img; 
	@FXML
	ComboBox<UserFaceGroup> groupOptions;
	
	@Autowired
	FaceEngineService faceEngineService;
	@Autowired
	UserFaceInfoService userFaceInfoService; 
	@Autowired
	UserFaceImgService userFaceImgService; 
	
	@Autowired
    private CheckFaceService checkFaceService;
 
	@Lazy
	@Autowired
	private StageManager stageManager;
	
	public static Long groupId = 1L;
	public static Webcam selWebCam = null;
	public static boolean stopCamera = false;
	
	private ObjectProperty<Image> imageProperty = new SimpleObjectProperty<Image>();
	
	private String cameraListPromptText = "选择摄像头";
	private String groupListPromptText = "选择人员分组";
	@FXML
	private Pane facePane; 
	static Map<String,String> webCams = null; 
	static{
		webCams = new HashMap<String,String>(){
			private static final long serialVersionUID = 1L;{ 
			put("安检摄像头","0"); 
		 }};  
	}
	@Override
	public void initialize(URL arg0, ResourceBundle arg1){

		fpBottomPane.setDisable(false); 
		btnBackToUser.setDisable(false);
		selectCam();
		setCamShow();  
//		isScanRunning = true; 
//		DaemonExcutor.serviceScan.execute(new ScanFace(faceQueue,count,faceEngineService,faceOne,faceTwo,faceThree,faceFour,faceFive));
		ExcutorUtil.isTakeRunning = true; 
	}
	
	 
	private void selectCam(){
		ObservableList<WebCamInfo> options = FXCollections.observableArrayList();
		int webCamCounter = 0;
		for (String webcam : webCams.keySet()) {
			options.add(WebCamInfo.builder().webCamIndex(webCams.get(webcam)).webCamName(webcam).build());
		} 
		cbCameraOptions.setItems(options);
		cbCameraOptions.setPromptText(cameraListPromptText);
		cbCameraOptions.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<WebCamInfo>(){
			@Override
			public void changed(ObservableValue<? extends WebCamInfo> arg0, WebCamInfo old, WebCamInfo newCam){
				if (newCam != null) {
					System.out.println("摄像头索引：" + newCam.getWebCamIndex() + ": 摄像头名称:" + newCam.getWebCamName());
					initializeWebCam(newCam.getWebCamIndex());
				}
			}
		});
	}
	
	protected void setCamShow(){
		Platform.runLater(new Runnable(){
			@Override
			public void run() {
				double height = img.getFitHeight();
				double width = img.getFitWidth();
				img.setFitHeight(height);
				img.setFitWidth(width);
				img.prefHeight(height);
				img.prefWidth(width);
				img.setPreserveRatio(true); 
			}
		}); 
	}

	protected void initializeGroup(final UserFaceGroup webCamIndex){
		groupId = webCamIndex.getId();
	}
	private FrameGrabber grabber = null;
	protected void initializeWebCam(final String webCamIndex){

		Task<Void> webCamIntilizer = new Task<Void>(){

			@Override
			protected Void call() throws Exception{
				stopCamera = true;
				Thread.sleep(1000);
				closeCamera(); 
				Thread.sleep(1000);
				grabber = OpenCVFrameGrabber.createDefault(Integer.valueOf(webCamIndex).intValue()); 
		        grabber.setOption("rtsp_transport", "tcp"); // 使用tcp的方式，不然会丢包很严重
		        grabber.start();
				startWebCamStream();  
				return null;
			} 
		};

		new Thread(webCamIntilizer).start();
		fpBottomPane.setDisable(false);
		btnStartCamera.setDisable(true);
	}

	protected void startWebCamStream() { 
		stopCamera = false;
		Task<Void> task = new Task<Void>() {

			@Override
			protected Void call() throws Exception {

				final AtomicReference<WritableImage> ref = new AtomicReference<>();
				BufferedImage img = null;
				Java2DFrameConverter conver = new Java2DFrameConverter();
				while (!stopCamera) {
					try { 
						Frame frame = null;
						try {
							frame = grabber.grab();
						} catch (Exception e){
							if(grabber != null){
								grabber.close();
							} 
							frame = null;
						} 
						if(frame == null){
							continue;
						}
						if((img = conver.convert(frame)) != null) {
 
							List<FaceInfo> faces = faceEngineService.detectFaces(img);
							if(CollectionUtil.isNotEmpty(faces)){  
								img = faceEngineService.drow(img);
								 
							}

							ref.set(SwingFXUtils.toFXImage(img, ref.get()));
							img.flush();  
							Platform.runLater(new Runnable() {

								@Override
								public void run() { 
									imageProperty.set(ref.get()); 
								}
							}); 
						}
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
				return null;
			}
		};
		 
		new Thread(task).start();
		img.imageProperty().bind(imageProperty); 
	}
	 
	public static void closeCamera(){
		stopCamera = true;
		if (selWebCam != null){
			selWebCam.close(); 
		}
	}

	public void stopCamera(ActionEvent event){
		stopCamera = true;
		btnStartCamera.setDisable(false);
		btnStopCamera.setDisable(true);
	}

	public void startCamera(ActionEvent event){
		stopCamera = false;
		startWebCamStream();
		btnStartCamera.setDisable(true);
		btnStopCamera.setDisable(false);
	}

	public void disposeCamera(ActionEvent event){
		stopCamera = true;
		closeCamera();
		btnStopCamera.setDisable(true);
		btnStartCamera.setDisable(true);
	}

	public void backToUser(ActionEvent event){
		stopCamera = true; 
		ExcutorUtil.isScanRunning = false;
		ExcutorUtil.isTakeRunning = false;
		stopCamera(event);
		stageManager.switchScene(FxmlView.USER);
	} 
	
	public void savePicture(ActionEvent event){
		ExcutorUtil.toTakePicture = true;
	}
	 
}
